
/// 采用网络字节序 既BE作为标准
public static class NetBitConverter
{
	private static bool CheckBuffer(byte[] bufer, int startIndex, int count)
	{
		if (bufer == null)
		{
			throw new System.NullReferenceException();
		}
		
		if (startIndex + count > bufer.Length)
		{
			throw new System.Exception("buffer no enough space");
		}
		
		return true;
	}

    public static void Write (byte[] bufer, int startIndex, bool v)
    {
    	if (CheckBuffer(bufer, startIndex, 1))
    	{
    		bufer[startIndex] = v ? (byte)1 : (byte)0;
    	}
    }


    public static void Write (byte[] bufer, int startIndex, byte v)
    {
        if (CheckBuffer(bufer, startIndex, 1))
    	{
    		bufer[startIndex] = v;
    	}
    }

    public static void Write (byte[] bufer, int startIndex, sbyte v)
    {
    	if (CheckBuffer(bufer, startIndex, 1))
    	{
    		bufer[startIndex] = (byte)v;
    	}
    }

    public static unsafe void Write (byte[] bufer, int startIndex, short v)
    {
    	if (CheckBuffer(bufer, startIndex, 2))
    	{
	    	byte* ptr = (byte*)(&v);
			if (System.BitConverter.IsLittleEndian)
			{
				bufer[startIndex    ] = ptr[1];
				bufer[startIndex + 1] = ptr[0];
			}
			else
			{
				bufer[startIndex    ] = ptr[0];
				bufer[startIndex + 1] = ptr[1];
			}
    	}
    }
    
    public static unsafe void Write (byte[] bufer, int startIndex, ushort v)
    {
    	if (CheckBuffer(bufer, startIndex, 2))
    	{
    		byte* ptr = (byte*)(&v);
			if (System.BitConverter.IsLittleEndian)
			{
				bufer[startIndex    ] = ptr[1];
				bufer[startIndex + 1] = ptr[0];
			}
			else
			{
				bufer[startIndex    ] = ptr[0];
				bufer[startIndex + 1] = ptr[1];
			}
    	}
    }

    public static unsafe void Write(byte[] bufer, int startIndex, int v)
    {
    	if (CheckBuffer(bufer, startIndex, 4))
    	{
	        byte* ptr = (byte*)(&v);
			if (System.BitConverter.IsLittleEndian)
			{
				bufer[startIndex    ] = ptr[3];
				bufer[startIndex + 1] = ptr[2];
				bufer[startIndex + 2] = ptr[1];
				bufer[startIndex + 3] = ptr[0];
			}
			else
			{
				bufer[startIndex    ] = ptr[0];
				bufer[startIndex + 1] = ptr[1];
				bufer[startIndex + 2] = ptr[2];
				bufer[startIndex + 3] = ptr[3];
			}
    	}
    }
    
    public static unsafe void Write(byte[] bufer, int startIndex, uint v)
    {
    	if (CheckBuffer(bufer, startIndex, 4))
    	{
	        byte* ptr = (byte*)(&v);
			if (System.BitConverter.IsLittleEndian)
			{
				bufer[startIndex    ] = ptr[3];
				bufer[startIndex + 1] = ptr[2];
				bufer[startIndex + 2] = ptr[1];
				bufer[startIndex + 3] = ptr[0];
			}
			else
			{
				bufer[startIndex    ] = ptr[0];
				bufer[startIndex + 1] = ptr[1];
				bufer[startIndex + 2] = ptr[2];
				bufer[startIndex + 3] = ptr[3];
			}
    	}
    }
    
    public static unsafe void Write(byte[] bufer, int startIndex, long v)
    {
    	if (CheckBuffer(bufer, startIndex, 8))
    	{
	        byte* ptr = (byte*)(&v);
			if (System.BitConverter.IsLittleEndian)
			{
				bufer[startIndex    ] = ptr[7];
				bufer[startIndex + 1] = ptr[6];
				bufer[startIndex + 2] = ptr[5];
				bufer[startIndex + 3] = ptr[4];
				bufer[startIndex + 4] = ptr[3];
				bufer[startIndex + 5] = ptr[2];
				bufer[startIndex + 6] = ptr[1];
				bufer[startIndex + 7] = ptr[0];
			}
			else
			{
				bufer[startIndex    ] = ptr[0];
				bufer[startIndex + 1] = ptr[1];
				bufer[startIndex + 2] = ptr[2];
				bufer[startIndex + 3] = ptr[3];
				bufer[startIndex + 4] = ptr[4];
				bufer[startIndex + 5] = ptr[5];
				bufer[startIndex + 6] = ptr[6];
				bufer[startIndex + 7] = ptr[7];
			}
    	}
    }
    
    public static unsafe void Write(byte[] bufer, int startIndex, ulong v)
    {
    	if (CheckBuffer(bufer, startIndex, 8))
    	{
	        byte* ptr = (byte*)(&v);
			if (System.BitConverter.IsLittleEndian)
			{
				bufer[startIndex    ] = ptr[7];
				bufer[startIndex + 1] = ptr[6];
				bufer[startIndex + 2] = ptr[5];
				bufer[startIndex + 3] = ptr[4];
				bufer[startIndex + 4] = ptr[3];
				bufer[startIndex + 5] = ptr[2];
				bufer[startIndex + 6] = ptr[1];
				bufer[startIndex + 7] = ptr[0];
			}
			else
			{
				bufer[startIndex    ] = ptr[0];
				bufer[startIndex + 1] = ptr[1];
				bufer[startIndex + 2] = ptr[2];
				bufer[startIndex + 3] = ptr[3];
				bufer[startIndex + 4] = ptr[4];
				bufer[startIndex + 5] = ptr[5];
				bufer[startIndex + 6] = ptr[6];
				bufer[startIndex + 7] = ptr[7];
			}
    	}
    }

    public static unsafe void Write(byte[] bufer, int startIndex, float v)
    {
    	if (CheckBuffer(bufer, startIndex, 4))
    	{
	        byte* ptr = (byte*)(&v);
			if (System.BitConverter.IsLittleEndian)
			{
				bufer[startIndex    ] = ptr[3];
				bufer[startIndex + 1] = ptr[2];
				bufer[startIndex + 2] = ptr[1];
				bufer[startIndex + 3] = ptr[0];
			}
			else
			{
				bufer[startIndex    ] = ptr[0];
				bufer[startIndex + 1] = ptr[1];
				bufer[startIndex + 2] = ptr[2];
				bufer[startIndex + 3] = ptr[3];
			}
    	}
    }

    public static unsafe void Write(byte[] bufer, int startIndex, double v)
    {
    	if (CheckBuffer(bufer, startIndex, 8))
    	{
	        byte* ptr = (byte*)(&v);
			if (System.BitConverter.IsLittleEndian)
			{
				bufer[startIndex    ] = ptr[7];
				bufer[startIndex + 1] = ptr[6];
				bufer[startIndex + 2] = ptr[5];
				bufer[startIndex + 3] = ptr[4];
				bufer[startIndex + 4] = ptr[3];
				bufer[startIndex + 5] = ptr[2];
				bufer[startIndex + 6] = ptr[1];
				bufer[startIndex + 7] = ptr[0];
			}
			else
			{
				bufer[startIndex    ] = ptr[0];
				bufer[startIndex + 1] = ptr[1];
				bufer[startIndex + 2] = ptr[2];
				bufer[startIndex + 3] = ptr[3];
				bufer[startIndex + 4] = ptr[4];
				bufer[startIndex + 5] = ptr[5];
				bufer[startIndex + 6] = ptr[6];
				bufer[startIndex + 7] = ptr[7];
			}
    	}
    }

   	private unsafe static void PutBytes (byte* dst, byte[] src, int startIndex, int count)
	{
		if (System.BitConverter.IsLittleEndian)
		{
			for (int i = 0; i < count; i++) 
				dst [count - i - 1] = src [i + startIndex];
		}
		else
		{
			for (int i = 0; i < count; i++) 
				dst [i] = src [i + startIndex];
		}
	}

    public static bool ReadBool (byte[] buffer, int startIndex)
    {
    	CheckBuffer(buffer, startIndex, 1);
		return buffer[startIndex] != 0;
    }

    public static sbyte ReadSByte (byte[] buffer, int startIndex)
    {
    	CheckBuffer(buffer, startIndex, 1);
        return (sbyte)buffer[startIndex];
    }

    public static byte ReadByte (byte[] buffer, int startIndex)
    {
    	CheckBuffer(buffer, startIndex, 1);
        return buffer[startIndex];
    }
    


    public static unsafe short ReadInt16 (byte[] buffer, int startIndex)
    {
    	CheckBuffer(buffer, startIndex, 2);
		short result;
		PutBytes((byte*)(&result), buffer, startIndex, 2);
		return result;
    }
    
    public static unsafe ushort ReadUInt16 (byte[] buffer, int startIndex)
    {
    	CheckBuffer(buffer, startIndex, 2);
        ushort result;
		PutBytes((byte*)(&result), buffer, startIndex, 2);
		return result;
    }

    public static unsafe int ReadInt32 (byte[] buffer, int startIndex)
    {
    	CheckBuffer(buffer, startIndex, 4);
        int result;
		PutBytes((byte*)(&result), buffer, startIndex, 4);
		return result;
    }

    public static unsafe uint ReadUInt32 (byte[] buffer, int startIndex)
    {
    	CheckBuffer(buffer, startIndex, 4);
        uint result;
		PutBytes((byte*)(&result), buffer, startIndex, 4);
		return result;
    }

    public static unsafe long ReadInt64 (byte[] buffer, int startIndex)
    {
    	CheckBuffer(buffer, startIndex, 8);
        long result;
		PutBytes((byte*)(&result), buffer, startIndex, 8);
		return result;
    }
    
    public static unsafe ulong ReadUInt64 (byte[] buffer, int startIndex)
    {
    	CheckBuffer(buffer, startIndex, 8);
        ulong result;
		PutBytes((byte*)(&result), buffer, startIndex, 8);
		return result;
    }

    public static unsafe float ReadFloat (byte[] buffer, int startIndex)
    {
    	CheckBuffer(buffer, startIndex, 4);
        float result;
		PutBytes((byte*)(&result), buffer, startIndex, 4);
		return result;
    }

    public static unsafe double ReadDouble (byte[] buffer, int startIndex)
    {
    	CheckBuffer(buffer, startIndex, 8);
        double result;
		PutBytes((byte*)(&result), buffer, startIndex, 8);
		return result;
    }
    /// 从 buffer 中读取 字符串
    public static byte[] ReadBytes (byte[] buffer, int startIndex, int count)
    {
        CheckBuffer(buffer, startIndex, count);
        byte[] bytes = new byte[count];
        System.Buffer.BlockCopy(buffer, startIndex, bytes, 0, count);
        return bytes;
    }


    /// 从 buffer 中读取 字符串
    public static string ReadString (byte[] buffer, int startIndex, int count)
    {
    	CheckBuffer(buffer, startIndex, count);
        return System.Text.Encoding.UTF8.GetString(buffer, startIndex, count);
    }

    public static string GetSbyteStringFromBytes(byte[] bytes)
    {
	    return GetSbyteStringFromBytes(bytes, 0, bytes.Length);
    }

    /// 此函数用于Debug时查看对比字节流
    public static string GetSbyteStringFromBytes (byte[] bytes, int offset, int count)
    {
    	if (bytes == null || count == 0) return "[]";
    	if (offset + count > bytes.Length)
    	{
    		throw new System.Exception("array out of bounds");
    	}
    	
		System.Text.StringBuilder sb = new System.Text.StringBuilder();
		sb.Append('[');
		for(int i = 0; i < count; ++i)
		{
			sb.Append((bytes[offset + i]).ToString().PadLeft(3, ' '));
			sb.Append(", ");
		}
		sb.Append(']');

		return sb.ToString();
    }
    
    public static bool Compare (byte[] src, byte[] dst)
    {
    	int srcLen = src == null? 0 : src.Length;
    	int dstLen = dst == null? 0 : dst.Length;
    	
    	if (srcLen != dstLen) return false;
    	if (srcLen == 0) return true;
    	
    	for(int i = 0; i < srcLen; ++i)
    	{
    		if (src[i] != dst[i]) return false;
    	}
    	
    	return true;
    }

	public static bool Compare (byte[] src, int srcStartIndex, int srcCount, byte[] dst, int dstStartIndex, int dstCount)
	{
		if (srcCount != dstCount) return false;
		if (srcCount == 0) return true;

		for(int i = 0; i < srcCount; ++i)
		{
			if (src[i + srcStartIndex] != dst[i + dstStartIndex]) return false;
		}

		return true;
	}

    /// 合并字节流
    public static byte[] Combine (params byte[][] buffer)
    {
        int bufferCount = buffer.Length;
        byte[] currentBuffer;
        int length = 0;
        for (int i = 0; i < bufferCount; ++i)
        {
            currentBuffer = buffer[i];
            if (currentBuffer != null)
            {
                length += currentBuffer.Length;
            }
        }

        byte[] newBuffer = new byte[length];
        int copyStartIndex = 0;

        for (int i = 0; i < bufferCount; ++i)
        {
            currentBuffer = buffer[i];
            if (currentBuffer != null)
            {
                length = currentBuffer.Length;
                if (length > 0)
                {
                    System.Buffer.BlockCopy(buffer[i], 0, newBuffer, copyStartIndex, length);
                    copyStartIndex += length;
                }
            }
        }

        return newBuffer;
    }
}